/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev

*/

package imageuploader.ui;


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;

public class FileTree  extends JTree
{
  public static final ImageIcon ICON_COMPUTER = 
    new ImageIcon("computer.gif");
  public static final ImageIcon ICON_DISK = 
    new ImageIcon("disk.gif");
  public static final ImageIcon ICON_FOLDER = 
    new ImageIcon("folder.gif");
  public static final ImageIcon ICON_EXPANDEDFOLDER = 
    new ImageIcon("expandedfolder.gif");

  protected DefaultTreeModel m_model;
  protected JTextField m_display;

  public FileTree()
  {

    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new IconData(ICON_COMPUTER, null, "Computer"));

    DefaultMutableTreeNode node;
    File[] roots = File.listRoots();
    for (int k=0; k<roots.length; k++)
    {
      node = new DefaultMutableTreeNode(new IconData(ICON_DISK, 
        null, new FileNode(roots[k])));
      top.add(node);
                        node.add( new DefaultMutableTreeNode(new Boolean(true)));
    }

    m_model = new DefaultTreeModel(top);
    setModel(m_model);

                putClientProperty("JTree.lineStyle", "Angled");

    TreeCellRenderer renderer = new 
      IconCellRenderer();
    setCellRenderer(renderer);

    addTreeExpansionListener(new 
      DirExpansionListener());

//    addTreeSelectionListener(new 
//      DirSelectionListener());

    getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION); 
    setShowsRootHandles(true); 
    setEditable(false);

  }

  public DefaultMutableTreeNode getTreeNode(TreePath path)
  {
    return (DefaultMutableTreeNode)(path.getLastPathComponent());
  }

  public FileNode getFileNode(DefaultMutableTreeNode node)
  {
    if (node == null)
      return null;
    Object obj = node.getUserObject();
    if (obj instanceof IconData)
      obj = ((IconData)obj).getObject();
    if (obj instanceof FileNode)
      return (FileNode)obj;
    else
      return null;
  }

    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener
    {
        public void treeExpanded(TreeExpansionEvent event)
        {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);

            Thread runner = new Thread(){
                @Override
                public void run(){
                    if (fnode != null && fnode.expand(node)){
                        Runnable runnable = new Runnable(){
                            public void run(){
                               m_model.reload(node);
                            }
                        };
                        SwingUtilities.invokeLater(runnable);
                    }
                }
            };
            runner.start();
        }

        public void treeCollapsed(TreeExpansionEvent event) {}
    }


//    class DirSelectionListener implements TreeSelectionListener{
//        public void valueChanged(TreeSelectionEvent event){
//            DefaultMutableTreeNode node = getTreeNode(event.getPath());
//            FileNode fnode = getFileNode(node);
//            System.out.println(fnode);
//            if (fnode != null){
//                m_display.setText(fnode.getFile().getAbsolutePath());
//            }else{
//                m_display.setText("");
//            }
//        }
//    }
//
//  public static void main(String argv[]) 
//  {
//    FileTree fileTree = new FileTree();
//    JFrame frm = new JFrame();
//    JScrollPane pane = new JScrollPane();
//    pane.getViewport().add(fileTree);
//    frm.getContentPane().add(pane);
//    frm.addWindowListener(new WindowAdapter(){
//        @Override
//        public void windowClosing(WindowEvent e){
//            System.exit(0);
//        }        
//    });
//    frm.setSize(300,400);
//    frm.setVisible(true);
//
//  }
}

class IconCellRenderer 
  extends    JLabel 
  implements TreeCellRenderer
{
  protected Color m_textSelectionColor;
  protected Color m_textNonSelectionColor;
  protected Color m_bkSelectionColor;
  protected Color m_bkNonSelectionColor;
  protected Color m_borderSelectionColor;

  protected boolean m_selected;

  public IconCellRenderer()
  {
    super();
    m_textSelectionColor = UIManager.getColor(
      "Tree.selectionForeground");
    m_textNonSelectionColor = UIManager.getColor(
      "Tree.textForeground");
    m_bkSelectionColor = UIManager.getColor(
      "Tree.selectionBackground");
    m_bkNonSelectionColor = UIManager.getColor(
      "Tree.textBackground");
    m_borderSelectionColor = UIManager.getColor(
      "Tree.selectionBorderColor");
    setOpaque(false);
  }

  public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean sel, boolean expanded, boolean leaf, 
    int row, boolean hasFocus) 
    
  {
    DefaultMutableTreeNode node = 
      (DefaultMutableTreeNode)value;
    Object obj = node.getUserObject();
    setText(obj.toString());

                if (obj instanceof Boolean)
                  setText("Retrieving data...");

    if (obj instanceof IconData)
    {
      IconData idata = (IconData)obj;
      if (expanded)
        setIcon(idata.getExpandedIcon());
      else
        setIcon(idata.getIcon());
    }
    else
      setIcon(null);

    setFont(tree.getFont());
    setForeground(sel ? m_textSelectionColor : 
      m_textNonSelectionColor);
    setBackground(sel ? m_bkSelectionColor : 
      m_bkNonSelectionColor);
    m_selected = sel;
    return this;
  }
    
    @Override
  public void paintComponent(Graphics g) 
  {
    Color bColor = getBackground();
    Icon icon = getIcon();

    g.setColor(bColor);
    int offset = 0;
    if(icon != null && getText() != null) 
      offset = (icon.getIconWidth() + getIconTextGap());
    g.fillRect(offset, 0, getWidth() - 1 - offset,
      getHeight() - 1);
    
    if (m_selected) 
    {
      g.setColor(m_borderSelectionColor);
      g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
    }
    super.paintComponent(g);
    }
}

class IconData
{
  protected Icon   m_icon;
  protected Icon   m_expandedIcon;
  protected Object m_data;

  public IconData(Icon icon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = null;
    m_data = data;
  }

  public IconData(Icon icon, Icon expandedIcon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = expandedIcon;
    m_data = data;
  }

  public Icon getIcon() 
  { 
    return m_icon;
  }

  public Icon getExpandedIcon() 
  { 
    return m_expandedIcon!=null ? m_expandedIcon : m_icon;
  }

  public Object getObject() 
  { 
    return m_data;
  }

    @Override
  public String toString() 
  { 
    return m_data.toString();
  }
}

